﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Jaiden.Runtime.InteropServices;
using Newtonsoft.Json;

namespace Jaiden.Net.Http
{
    public class JaidenHttpMessageHandler : HttpMessageHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var jr = new JaidenRequest();
            await jr.Load(request);
            var str = JsonConvert.SerializeObject(jr);
            TaskCompletionSource<HttpResponseMessage> source = new TaskCompletionSource<HttpResponseMessage>();
            UnsafeNativeMethods.Send(str, w =>
            {
                var json = UTF8Marshaler.PtrToStringUTF8(w.IntPtr);
                var response = JsonConvert.DeserializeObject<JaidenResponse>(json);
                if (response.Errors != null && response.Errors.Any())
                {
                    source.SetException(response.Errors.Select(i => new Exception(i)));
                }
                else
                {
                    var message = new HttpResponseMessage(response.StatusCode) { RequestMessage = request };

                    if (response.Headers != null && response.Headers.Any())
                    {
                        foreach (var header in response.Headers)
                        {
                            message.Headers.TryAddWithoutValidation(header.Key, header.Value);
                        }
                    }

                    if (response.Body != null)
                    {
                        var content = message.Content = new ByteArrayContent(response.Body);
                        if (response.Headers != null && response.Headers.Any())
                        {
                            foreach (var header in response.Headers)
                            {
                                content.Headers.TryAddWithoutValidation(header.Key, header.Value);
                            }
                        }
                    }

                    source.SetResult(message);
                }
            });
            return await source.Task;
        }
    }
}
